home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / windows3 / mdit.zip / MDIT_SRC.ZIP / THREAD.C < prev   
C/C++ Source or Header  |  1992-03-31  |  11KB  |  325 lines

  1. /****************************************************************************
  2. Module name: MDIT.C
  3. Programmer : Jeffrey M. Richter & Elvira Peretsman.
  4. Modified   : V. M. Vanderburg & M.T. Peterson, TriTechnologies
  5.                    -    Converted to multithreading
  6.                    -    Removed original comments
  7. ATTRIBUTIONS:
  8.  
  9.     With the exception of the PCthread calls, this code was taken directly
  10.     from the source disk furnished with the Windows Developer's Guide,
  11.     M&T Press, by Jeffrey M. Richter.  I highly recommend Mr. Richter's
  12.     book both for its readability and the structure and quality of the
  13.     code.
  14. *****************************************************************************/
  15.  
  16. /*
  17. #include "..\nowindws.h"
  18. #undef NOCOLOR
  19. #undef NOGDI
  20. #undef NOKERNEL
  21. #undef NOLSTRING
  22. #undef NOMB
  23. #undef NOMDI
  24. #undef NOMENUS
  25. #undef NOUSER
  26. #undef NOWINMESSAGES
  27. #undef NOWINOFFSETS
  28. */
  29. #include <windows.h>
  30.  
  31. #include "mdit.h"    /* includes pcthread.h */
  32. #include <errno.h>
  33. #include <except.h>
  34.  
  35. extern pcthread_attr_t g_th_attr;
  36.  
  37. static char _szClassName[] = "Thread";
  38.  
  39. typedef struct 
  40. {
  41.    HMENU hMenu;
  42.    HANDLE hAccelTable;
  43.    pcthread_t *pcth_p;
  44.  
  45. } CLSEB;
  46.  
  47. /************************* Drawing routines ****************************/
  48. static void DrawRectangle( HWND hwnd )
  49. {
  50.     HBRUSH    hBrush;
  51.     HDC       hdc;
  52.     RECT      r;
  53.     short     xLeft, xRight, yTop, yBottom, nRed, nGreen, nBlue;
  54.  
  55.     GetClientRect( hwnd, &r );
  56.     if( (r.right == 0) || (r.bottom == 0) )
  57.          return;
  58.  
  59.     xLeft = rand() % r.right;
  60.     xRight = rand() % r.right;
  61.     yTop = rand() % r.bottom;
  62.     yBottom = rand() % r.bottom;
  63.  
  64.     nRed = rand() & 255;
  65.     nGreen = rand() & 255;
  66.     nBlue = rand() & 255;
  67.  
  68.     hdc = GetDC( hwnd );
  69.     hBrush = CreateSolidBrush( RGB(nRed, nGreen, nBlue) );
  70.     SelectObject(hdc, hBrush );
  71.     
  72.     Rectangle(hdc, min(xLeft, xRight), min(yTop, yBottom),
  73.                    max(xLeft, xRight), max(yTop, yBottom) );
  74.                    
  75.     ReleaseDC(hwnd, hdc);
  76.     DeleteObject(hBrush);
  77. }
  78.  
  79. /*-------------------------------------------------------------------*/
  80. /*  DrawLoop()                                                       */
  81. /*-------------------------------------------------------------------*/
  82. /*  ACTION:                                                          */
  83. /*                                                                   */
  84. /*  This is the function that is passed to the pcthread_create()     */
  85. /*  routine and is known as the thread action routine.  Each thread  */
  86. /*  executes this loop over and over until it is cancelled or the    */
  87. /*  application terminates.                                          */
  88. /*                                                                   */
  89. /*  In this loop, each thread draws a single rectangle in the child  */
  90. /*  window it 'owns' and then yields control to any other threads    */
  91. /*  that are waiting on the thread ready queue -- Hence the name     */
  92. /*  pcthread_yield().                                                */
  93. /*-------------------------------------------------------------------*/
  94.  
  95. void FAR DrawLoop(pcthread_addr_t parameter)
  96. {
  97.     HWND hwnd;
  98.  
  99.     hwnd = (HWND) parameter;
  100.     for (;;)
  101.     {
  102.         DrawRectangle(hwnd);
  103.         pcthread_yield();
  104.         pcthread_testcancel();
  105.     }
  106. }
  107.  
  108. /************************** Child Message Loop ****************************/
  109. LONG FAR PASCAL ThreadProc (HWND hWnd, WORD wMsg, WORD wParam, LONG lParam) {
  110.    BOOL fCallDefProc = FALSE;
  111.    DWORD dwResult = 0;
  112.    WORD wTemp = 0;
  113.    HMENU hMenu;
  114.    char szBuf[100], szString[100], szCaption[25];
  115.    pcthread_t *th_p;
  116.    int stat;
  117.  
  118.    switch (wMsg) 
  119.    {
  120.       case WM_CREATE:
  121.          
  122.          if (GETCLSEB(hWnd, CLSEB, hMenu) == NULL) 
  123.          {
  124.             wTemp = LoadMenu(g_hInstance, _szClassName);
  125.             SETCLSEB(hWnd, CLSEB, hMenu, (HMENU) wTemp);
  126.             wTemp = LoadAccelerators(g_hInstance, _szClassName);
  127.             SETCLSEB(hWnd, CLSEB, hAccelTable, (HANDLE) wTemp); 
  128.          }
  129.  
  130.          th_p = (pcthread_t *) pcthread_malloc_np(sizeof(pcthread_t));
  131.          if (th_p == NULL)
  132.          {
  133.             MessageBox(hWnd, "Out of memory.", g_szAppName, MB_OK);
  134.             break;
  135.          }
  136.  
  137.          /*
  138.           *   --   Create a child thread that is to execute the
  139.           *        DrawLoop() function.  If the call fails for
  140.           *        any reason, a -1 will be returned in which case
  141.           *        we try to gracefully terminate the application.
  142.           */
  143.  
  144.          stat = pcthread_create(th_p, 
  145.                           g_th_attr, 
  146.                           (pcthread_action_t) DrawLoop, 
  147.                   (pcthread_addr_t *) hWnd);
  148.          if( stat < 0 )
  149.               pcthread_shutdown_np("","", 
  150.                                    "pcthread_create() failed",
  151.                                    client_exception_e );
  152.  
  153.          /*
  154.           *   --   The pcthread_detach() call instructs the thread
  155.           *        kernel to recover and reutilize the memory and other
  156.           *        objects (mutexes and condition variables) from which
  157.           *        the thread was created.  Threads that are not detached
  158.           *        hang around until the application terminates.
  159.           *
  160.           *        Why not detach all threads?  Well, because there is
  161.           *        another service called pcthread_join() that allows you
  162.           *        to obtain the return values, if any, from the thread's
  163.           *        action routine.  In this application, there are none so
  164.           *        we might as well detach 'em immediately.
  165.           */
  166.           
  167.          stat = pcthread_detach(th_p);
  168.          if( stat < 0 )
  169.               pcthread_shutdown_np("","", 
  170.                                    "pcthread_detach() failed",
  171.                                    client_exception_e );
  172.  
  173.          /*
  174.           *   --   This 'attaches' the thread's handle, th_p, to a
  175.           *        specific window.
  176.           */
  177.  
  178.          SetWindowWord( hWnd, 0, (WORD) th_p);
  179.  
  180.          break;
  181.  
  182.       case WM_MDIACTIVATE: 
  183.          if (wParam == FALSE) break;
  184.          
  185.          ChangeMDITMenu(GETFRAME(hWnd), GetParent(hWnd),
  186.             (HMENU) GETCLSEB(hWnd, CLSEB, hMenu), IDM_WINDOWTILEVERT);
  187.          g_hAccelTable = (HANDLE) GETCLSEB(hWnd, CLSEB, hAccelTable);
  188.          
  189.          InvalidateRect(GETFRAME(hWnd), NULL, TRUE);
  190.          break;
  191.  
  192.       case WM_CLOSE:
  193.          
  194.          fCallDefProc = TRUE;
  195.          SendMessage(hWnd, WM_ENDSESSION, TRUE, 0);
  196.          break;
  197.  
  198.       case WM_QUERYENDSESSION:
  199.          dwResult = TRUE;
  200.          break;
  201.  
  202.       case WM_ENDSESSION:
  203.          
  204.          break;
  205.  
  206.       case WM_DESTROY:
  207.          
  208.          /*
  209.           *   --   Here we obtain the handle of the thread associated
  210.           *        with the window being cancelled.  As a multithreaded
  211.           *        program, we have to remember to cancel the thread
  212.           *        as well as destroy the child window.
  213.           */
  214.           
  215.      th_p = (pcthread_t *) GetWindowWord(hWnd, 0 );
  216.          PostMessage(GETFRAME(hWnd), FW_MDITCHILDDESTROY, hWnd, 0);
  217.          fCallDefProc = TRUE;
  218.  
  219.          if (th_p != NULL)
  220.         pcthread_cancel( *th_p );
  221.  
  222.          break;
  223.  
  224.       case AC_PAINTSTATBAR:
  225.          
  226.          LoadString(g_hInstance, IDS_THREADSTATUSBAR, szBuf, sizeof(szBuf));
  227.  
  228.          ((LPPAINTSTRUCT) lParam)->rcPaint.top += (int) 
  229.             SendMessage(GETFRAME(hWnd), FW_DRAWSTATUSDIVIDE, 0,
  230.             (LONG) (LPPAINTSTRUCT) lParam);
  231.  
  232.          TextOut((HDC) wParam, 0, ((LPPAINTSTRUCT) lParam)->rcPaint.top,
  233.             szBuf, lstrlen(szBuf));
  234.          break;
  235.  
  236.       case WM_MENUSELECT:
  237.  
  238.          if (lParam == MAKELONG(-1, 0)) 
  239.          {
  240.             SendMessage(GETFRAME(hWnd), FW_SETMENUHELP, 0, 0);
  241.             break;
  242.          }
  243.  
  244.          switch (LOWORD(lParam) & (MF_POPUP | MF_SYSMENU))
  245.          {
  246.             case 0:
  247.                if ((wParam > IDM_WINDOWCHILD) && (wParam <= IDM_WINDOWCHILD + 9))
  248.                   wParam = IDM_WINDOWCHILD;
  249.                
  250.                wTemp = IDS_THREADMENUID + wParam;
  251.                break;
  252.  
  253.             case MF_POPUP:
  254.                hMenu = GetMenu(GETFRAME(hWnd));
  255.                wTemp = GetMenuItemCount(hMenu);
  256.                while (wTemp--) 
  257.                   if (GetSubMenu(hMenu, wTemp) == (HMENU) wParam) break;
  258.                wTemp += IDS_THREADPOPUPID;
  259.                if (!IsZoomed(hWnd)) wTemp++;
  260.                break;
  261.  
  262.             case MF_SYSMENU:
  263.                wTemp = IDS_THREADMENUID + ((wParam & 0x0FFF) >> 4);
  264.                break;
  265.  
  266.             case MF_POPUP | MF_SYSMENU:
  267.                wTemp = IDS_THREADPOPUPID;
  268.                break;
  269.          }
  270.          
  271.          SendMessage(GETFRAME(hWnd), FW_SETMENUHELP, hWnd, wTemp);
  272.          break;
  273.  
  274.       case WM_ENTERIDLE:
  275.          SendMessage(GETFRAME(hWnd), wMsg, wParam, lParam);
  276.          break;
  277.  
  278.       case AW_PAINTMENUHELP:
  279.          dwResult = SendMessage(GETFRAME(hWnd), FW_GETMENUHELP, 0, 0);
  280.          ((LPPAINTSTRUCT) lParam)->rcPaint.top += (int) 
  281.             SendMessage(GETFRAME(hWnd), FW_DRAWSTATUSDIVIDE, 0,
  282.             (LONG) (LPPAINTSTRUCT) lParam);
  283.          
  284.          LoadString(g_hInstance, LOWORD(dwResult), szString, sizeof(szString));
  285.          GetWindowText(hWnd, szCaption, sizeof(szCaption));
  286.          wsprintf(szBuf, szString, (LPSTR) szCaption);
  287.          
  288.          TextOut(((LPPAINTSTRUCT) lParam)->hdc,
  289.             0, ((LPPAINTSTRUCT) lParam)->rcPaint.top, szBuf, lstrlen(szBuf));
  290.          break;
  291.  
  292.       case WM_COMMAND:
  293.          
  294.          MessageBox(hWnd, "Option not implemented.", g_szAppName, MB_OK);
  295.          break;
  296.  
  297.       default: fCallDefProc = TRUE; break;
  298.    }
  299.  
  300.    if (fCallDefProc)
  301.       dwResult = DefMDIChildProc(hWnd, wMsg, wParam, lParam);
  302.  
  303.    return(dwResult);
  304. }
  305.  
  306.  
  307. BOOL FAR PASCAL RegisterThreadWndClass (void) 
  308. {
  309.    WNDCLASS wc;
  310.  
  311.    wc.style          = 0;
  312.    wc.lpfnWndProc    = ThreadProc;
  313.    
  314.    wc.cbClsExtra     = sizeof(CLSEB);
  315.  
  316.    wc.cbWndExtra     = 0;
  317.    wc.hInstance      = g_hInstance;
  318.    wc.hIcon          = LoadIcon(g_hInstance, _szClassName);
  319.    wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
  320.    wc.hbrBackground  = COLOR_WINDOW + 1;
  321.    wc.lpszMenuName   = NULL;
  322.    wc.lpszClassName  = _szClassName;
  323.    return(RegisterClass(&wc));
  324. }
  325.